<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>class.js</title>
</head>
<body>
    
<script src="class.js"></script>

<script>

'use strict';

if(!("console" in window) || console == null){
    var console = {};
    console.log = function(){
        document.write([].slice.call(arguments).join(",") + "<br>")
    };
}

var assert = function(value, msg){
    if(!value){
        throw(new Error(msg||(value+" does not equal true")));
    }
};

var assertEqual = function(val1, val2, msg){
    if(val1 !== val2){
        throw(new Error(msg || (val1 + " does not equal " + val2)));
    }
};


console.log("==================定义类（原生）===================");
(function(){

    var  AAA = function(){
        this.a = 1+2;
    };
    AAA.prototype.aa = function() {
        console.log('aa');
    };
    AAA.prototype.constructor = AAA;

    var a1 = new AAA();
    var a2 = $Class['new'](AAA);
    AAA.apply(a2);

    assert(a1.a == 3);
    assert(a2.a == 3);
    assert(a1 instanceof AAA);
    assert(a2 instanceof AAA);
    assert("aa" in a1);
    assert("aa" in a2);

    console.log(a1, a1.constructor,  a2, a2 instanceof AAA);

    for(var j in a1){
        console.log(j, a1[j]);
    }
    for(var k in a2){
        console.log(k, a2[k]);
    }

    console.log(a1.a==3, a2.a==3);


    //
    var A = function(){
        return {'ff':1};
    };

    var a3 = new A();
    var a4 = $Class['new'](A);
    A.apply(a4);

    console.log(a3, a4);


    assert("ff" in a3);
    assert("ff" in a4);
    assert(a3.ff == 1);
    assert(a4.ff == 1);


})();


console.log("==================定义类（$Class.create）===================");
(function(){
    $Class.config({
        disguise:true
    });
    

    var AAA = $Class.create({
        __:function(){
            this.a = 1+2;
        },
        aa:function(){
            console.log('aa')
        }
    });

    var a1 = new AAA();
    var a2 = $Class['new'](AAA);
    AAA.apply(a2);

    assert(a1.a == 3);
    assert(a2.a == 3);
    assert(a1 instanceof AAA);
    assert(a2 instanceof AAA);
    assert("aa" in a1);
    assert("aa" in a2);



    console.log(a1, a1.constructor,  a2, a2 instanceof AAA);

    for(var j in a1){
        console.log(j, a1[j]);
    }
    for(var k in a2){
        console.log(k, a2[k]);
    }

    console.log(a1.a==3, a2.a==3);



    var A = $Class.create({
        __:function(){
            return {'ff':1};
        }
    });

    var a3 = new A();
    var a4 = A();

    console.log(a3, a4);

    assert("ff" in a3);
    assert("ff" in a4);
    assert(a3.ff == 1);
    assert(a4.ff == 1);
    
    console.log("拓展：");


    console.log("$super:",a1.constructor.$super,"$extend:", a1.constructor.$extend,"$constructor:",a1.constructor.$constructor)

})();






console.log("==================继承===================");
(function(){

var BBB = $Class.create({
    __:function(){
        this.colors = ['red', 'blue', 'green'];
    }
})

var CCC = BBB.$extend({
    __:function(){
        CCC.$super.constructor.call(this);
    },
    aa:function(){}
});


var b1 = new BBB();
console.log("b1", b1);
b1.colors.push("black");
BBB.prototype.add = 1;

assert(b1.colors.length == 4);
assert("add" in b1);

var c1 = new CCC();
c1.colors.push("yellow");

assert(c1.colors.length == 4);
assert(c1.colors[3] == 'yellow');
assert(c1.constructor === CCC);
assert(c1.constructor.prototype === CCC.prototype);

var c2 = $Class['new'](CCC);
CCC.apply(c2);

console.log(c1, c1.constructor,  c2, c2 instanceof CCC);

assert(c2.constructor === CCC);
assert(c2.constructor.prototype === CCC.prototype);



})();



console.log("==================成员检测===================");
(function(){

var CCC = $Class.create({a:1, add:function(){}});    
var D = CCC.$extend({bb:1});
var E = D.$extend({cc:1});
var F = E.$extend({dd:1});
var G = F.$extend({ee:1});

//CCC.prototype = G.prototype;//循环的链
console.log($Class.member(G));


var H = function(){}
H.prototype={
    a1:"a1",
    constructor:{
        prototype:{
            b1:"b1",
            constructor:{
                prototype:{
                    c1:"c1",
                    constructor:{
                        prototype:{
                            c1:"c2",
                            d1:"d1",//覆盖属性
                            d2:"d2",
                            constructor:Object
                        }
                    }
                }
            } 
        }
    }
    
};



console.log($Class.member(H));

})();


(function(){

console.log("==================单例类===================");

var S = $Class.singleton({
    __:function(){
        this.a = this.a + 1;
    },
    a:1,
    C:"创建的一个单例"
});

var s1 = S();
var s2 = new S();

s1.Name = "foo";


assert(s1 === s2);

console.log(s1===s2, s1,s2 ,s2.Name, s2.a);

})();

</script>
</body>
</html>
